package cn.ijero.contactlist.main

import android.app.Application
import androidx.lifecycle.viewModelScope
import cn.ijero.contactlist.app.BaseViewModel
import cn.ijero.contactlist.database.database
import cn.ijero.contactlist.database.table.Contact
import com.github.promeg.pinyinhelper.Pinyin
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch

class MainViewModel(application: Application) : BaseViewModel(application) {

    private val _contactList = MutableSharedFlow<List<Contact>>()
    val contactList: Flow<List<Contact>> = _contactList

    private val database by lazy {
        context.database
    }

    fun loadData() {
        viewModelScope.launch {
            val oldList = database.contactDao().findAll()
            if (oldList.isEmpty()) {
                val json = context.assets.open("contact.json").reader().readText()
                val srcList = Gson().fromJson<List<Contact>>(
                    json,
                    object : TypeToken<List<Contact>>() {}.type
                )

                val newList = srcList.map {
                    val name = it.name
                    var (pinyin, shouPin) = toPinyinAndShoupin(name)
                    it.pinYin = pinyin.uppercase()
                    it.shouPin = shouPin.uppercase()
                    it
                }

                database.contactDao().insert(*newList.toTypedArray())
            }

            val list = database.contactDao().findAll()
            _contactList.emit(list)
        }
    }

    private fun toPinyinAndShoupin(text: String): Pair<String, String> {
        var pinyin = ""
        var shouPin = ""
        for (nameChar in text) {
            val charPinyin = Pinyin.toPinyin(nameChar)
            pinyin += "$charPinyin,"
            shouPin += "${charPinyin.first()},"
        }
        pinyin = pinyin.removeSuffix(",")
        shouPin = shouPin.removeSuffix(",")
        return Pair(pinyin, shouPin)
    }

    fun search(text: String) {
        viewModelScope.launch {
            val oldList = database.contactDao().findAll()
            val resultList = mutableSetOf<Contact>()

            val (pinyin, shouPin) = toPinyinAndShoupin(text)

            for (contact in oldList) {
                if (contact.name.uppercase().contains(text.uppercase())) {
                    resultList.add(contact)
                } else if (
                    contact.pinYin.contains(pinyin.uppercase()) ||
                    contact.pinYin.contains(text.uppercase())
                ) {
                    resultList.add(contact)
                } else if (
                    contact.shouPin.contains(shouPin.uppercase()) ||
                    contact.shouPin.contains(text.uppercase())
                ) {
                    resultList.add(contact)
                } else {
                    if (
                        contact.pinYin.replace(",", "").contains(text.uppercase()) ||
                        contact.shouPin.replace(",", "").contains(shouPin.uppercase())
                    ) {
                        resultList.add(contact)
                    }
                }
            }
            _contactList.emit(resultList.toMutableList())
        }
    }
}